﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

using System.Text;
using System.Windows;

using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace client
{
    public partial class Form1 : Form
    {



        bool Connected = false;

        IPEndPoint ipep;// = new IPEndPoint(
                //IPAddress.Parse("127.0.0.1"), 11000);
        Socket server = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

        //
        int tryOutCount = 10;//number of tryouts on bad response
        int tryOuts;
        //
        Thread updateThread;

        //Queue emplementation
        public Queue<string> Queue = new Queue<string>();


        public Form1()
        {
            InitializeComponent();
        }

        void Update()
        {
            while (true)
            {
                Thread.Sleep(500);
                //ConsoleWrite("Wait loop quant");
                
                byte[] data = new byte[4096];
                //string input, stringData;

                if (Connected == true)
                {
                    //send welcome
                    string welcome;

                    welcome = "welcomeclient";
                    ConsoleWrite("welcome send");
                    data = Encoding.ASCII.GetBytes(welcome);
                    server.Send(data, data.Length,
                             SocketFlags.None);


                    
                    int recv = server.Receive(data);
                    string answerData = Encoding.UTF8.GetString(data, 0, recv);

                    ConsoleWrite(answerData);
                    if (answerData == "serverok")
                    {
                        ConsoleWrite("welcome from server received");
                        EnterMessageLoop();
                   }
                }
            }
        }

        void EnterMessageLoop()
        {
            byte[] data = new byte[4096];
            while (true)
            {
                string message = "empty";
                if (Queue.Count <= 0)
                {
                    message = "empty";
                }
                else
                {
                    message = Queue.Dequeue();
                }
                SendPacket(message);


                Thread.Sleep(500);

                string Message;

                Message = ReceivePacket();

                if (Message == "disconnect")
                {
                    Disconnect();
                }
                //ConsoleWrite("Answer received: ");
                //ConsoleWrite(Message+"\n");
                try
                {
                    string[] MessageSplit = Message.Split(new Char[] { '|' });

                    if (MessageSplit[0] == "message")
                    {
                        //DisplayMessage("this is message from server!");
                        ConsoleWrite("Server: " + MessageSplit[1] + "\n");
                        //ConsoleWrite(MessageSplit[1]);
                    }
                }
                catch
                {
                    Disconnect();
                }
            }
 
        }

        public void SendPacket(string msg)
        {
            //ConsoleWrite(msg);
            try
            {
                byte[] data = new byte[4096];
                data = Encoding.UTF8.GetBytes(msg);
                server.Send(data, data.Length,
                         SocketFlags.None);
                tryOuts = 0;
            }
            catch
            {
                ConsoleWrite("SendPacket error\n");
                tryOuts++;
                if (tryOuts >= tryOutCount) Disconnect();
            }
        }
        public void Disconnect()
        {
            ConsoleWrite("Client disconnected\n");
            updateThread.Abort();
        }

        public void Connect()
        {

        }

        public string ReceivePacket()
        {
            try
            {
                byte[] receiveMessage = new byte[4096];
                int recmsg = server.Receive(receiveMessage);
                string Message = Encoding.UTF8.GetString(receiveMessage, 0, recmsg);
                //ConsoleWrite(Message);
                tryOuts = 0;
                return Message;
            }
            catch
            {
                ConsoleWrite("ReceivePacket error\n");
                tryOuts++;
                if (tryOuts >= tryOutCount) Disconnect();
                return null;
            }
        }

        public delegate void ConsoleWriteDelegate(string msg);

        public void ConsoleWrite(string msg)
        {
            if (RichConsole.InvokeRequired == true)
            {
                // this is worker thread
                this.Invoke(new ConsoleWriteDelegate(ConsoleWrite), msg);
            }
            else
            {
                RichConsole.Text += msg;
                RichConsole.Text += "\n";

                RichConsole.SelectionStart = RichConsole.Text.Length;
                RichConsole.ScrollToCaret();
            }
        }


        void DisplayMessage(string msg)
        {
            MessageBox.Show(msg);
        }

        private void button1_Click(object sender, EventArgs e)
        {

            try
            {

                ipep = new IPEndPoint(
                    IPAddress.Parse(textBox2.Text), 11000);
                server = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

                server.Connect(ipep);

                updateThread = new Thread(new ThreadStart(Update));
                updateThread.Start();

                Connected = true;
            }
            catch// (SocketException e)
            {
                ConsoleWrite("Unable to connect to server.");
                ConsoleWrite(e.ToString());
                Connected = false;
                return;
            }

        }

        public void SendMessage(string msg)
        {
            Queue.Enqueue("message|" + msg);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            SendPacket("disconnect");
            System.Environment.Exit(1);
        }

        private void button2_Click(object sender, EventArgs e)
        {
            SendMessage(InputText.Text);
        }
    }
}
